﻿using Flurl.Http;
using NPOI.SS.Formula.Functions;
using Pay.Core;
using Pay.DTO;
using Pay.DTO.rpayBh127;
using Pay.IService;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pay.Service.Pay
{
    public class RpayBh127Service : ServiceBase2, IPayService, IDisposable
    {
        private IUnitOfWork _iUnitOfWork;
        private ISettingService _iSettingService;
        private IMerchantService _iMerchantService;
        private IChargeService _iChargeService;
        private IProfitDayService _iProfitDayService;
        private IBillService _iBillService;
        private IPayHtmlService _iPayHtmlService;
        private IRegionService _iRegionService;
        private RpayBh127Sign _rpay127Sign;

        public RpayBh127Service(IUnitOfWork iUnitOfWork, ISettingService iSettingService,
                                IMerchantService iMerchantService, IChargeService iChargeService,
                                IProfitDayService iProfitDayService, IBillService iBillService,
                                IPayHtmlService iPayHtmlService, IRegionService iRegionService) : base(iUnitOfWork)
        {
            _iUnitOfWork = iUnitOfWork;
            _iSettingService = iSettingService;
            _iMerchantService = iMerchantService;
            _iChargeService = iChargeService;
            _iProfitDayService = iProfitDayService;
            _iBillService = iBillService;
            _iPayHtmlService = iPayHtmlService;
            _iRegionService = iRegionService;
            _rpay127Sign = new RpayBh127Sign();
        }

        public Task<transfer_result> AgencyFund(apply_receive model)
        {
            throw new NotImplementedException();
        }

        public Task<certify_verify_result> CertifyVerify(certify_verify model)
        {
            throw new NotImplementedException();
        }

        public int DealItp(long id)
        {
            throw new NotImplementedException();
        }

        public Task<gateway_pay_result> GatewayPay(gateway_pay_model model)
        {
            throw new NotImplementedException();
        }

        public List<type_setting> GatewayPayBank()
        {
            throw new NotImplementedException();
        }

        public Task<pay_notity> GatewayPayQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayPayRefund(refund_model model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayRefundQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model_sms model)
        {
            throw new NotImplementedException();
        }

        public Task<int> ItpToFile(DateTime create_date)
        {
            throw new NotImplementedException();
        }

        public Task<mall_result> MallPay(mall_model obj)
        {
            throw new NotImplementedException();
        }

        public Task<merchant_register_result> MerchantModify(long bind_id, string settle_type, PayChannel channel = PayChannel.None)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 商户进件
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="opt"></param>
        /// <returns></returns>
        public async Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt)
        {
            if (opt == "A")
            {
                var model = new rpayBh127_merchant_reg_request();
                model.pay_type = "12701";
                model.nonce_str = DtoHelper.RandCode(10);
                SetMerchantInfo(model, dto);
                SetPayType(model, dto);
                var resultApi = await _rpay127Sign.PayGateway<rpayBh127_merchant_reg_resp>(model, "/api/jfv1/report");
                if (resultApi != null)
                {
                    if (resultApi.status == "0000")
                    {
                        if (resultApi.result_code == "0000")
                        {
                            dto.reg_merchant_no = resultApi.mch_id;
                            return ApiResultToJson.Json(new merchant_register_result { merchant_no = dto.reg_merchant_no });
                        }
                        else
                        {
                            return ApiResultToJson.Json<merchant_register_result>(resultApi.result_msg);
                        }
                    }
                    else
                    {
                        return ApiResultToJson.Json<merchant_register_result>(resultApi.message);
                    }
                }
            }
            else
            {
                var merchantReg = _iMerchantService.GetRegister(dto.id_card, dto.pay_channel);
                if (merchantReg != null)
                {
                    if (merchantReg.mobile != dto.mobile || merchantReg.account_no != dto.account_no)
                    {
                        var model = new rpayBh127_merchant_update_request
                        {
                            nonce_str = DtoHelper.RandCode(10),
                            pay_type = "12702",
                            phone = dto.mobile,
                            bankno = dto.account_no,
                            mch_id = merchantReg.merchant_no,
                            feerate = (dto.fee * 1000).ToString("0.0"),
                            witdraw_fee = dto.settle
                        };
                        var resultApi = await _rpay127Sign.PayGateway<rpayBh127_merchant_reg_resp>(model, "/api/jfv1/upReportInfo");
                        if (resultApi != null)
                        {
                            if (resultApi.status == "0000")
                            {
                                if (resultApi.result_code == "0000")
                                {
                                    dto.reg_merchant_no = resultApi.mch_id;
                                    return ApiResultToJson.Json(new merchant_register_result { merchant_no = dto.reg_merchant_no });
                                }
                                else
                                {
                                    return ApiResultToJson.Json<merchant_register_result>(resultApi.result_msg);
                                }
                            }
                            else
                            {
                                return ApiResultToJson.Json<merchant_register_result>(resultApi.message);
                            }
                        }
                    }
                    else
                    {
                        return ApiResultToJson.Json(new merchant_register_result { merchant_no = merchantReg.merchant_no });
                    }
                }
            }

            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        private void SetPayType(rpayBh127_merchant_reg_request model, merchant_register_model user)
        {
            model.feerate = (user.fee * 1000).ToString("0.0");
            model.witdraw_fee = user.settle;
        }

        private void SetMerchantInfo(rpayBh127_merchant_reg_request model, merchant_register_model authinfo)
        {
            model.bankno = authinfo.account_no;
            model.bankname = authinfo.bank_name;
            if (model.bankname == "邮政储蓄银行") model.bankname = "储蓄银行";
            else if (model.bankname == "广发银行股份有限公司") model.bankname = "广发银行";
            else if (model.bankname == "中国工商银行") model.bankname = "工商银行";
            else if (model.bankname == "中国建设银行") model.bankname = "建设银行";
            model.name = authinfo.account_name;
            model.idcard = authinfo.id_card;
            model.phone = authinfo.mobile;
            model.merch_name = authinfo.account_name;
            model.merch_shortname = authinfo.account_name;
            var regions = _iRegionService.GetRegionNames(authinfo.region_id).Split(' ');
            model.province = regions[0];
            model.city = regions.Length > 1 ? regions[1] : regions[0];
            model.area = regions.Length > 2 ? regions[2] : "";
            model.address = model.province + model.city;
            model.name = authinfo.account_name;
            model.bankcode = SetMerchantBankCode(authinfo.bank_code);
            model.bankbranch = authinfo.branch_name;
        }

        private string SetMerchantBankCode(string bank_code)
        {
            var banks = new Dictionary<string, string>();
            banks.Add("ABC", "103100000026");
            banks.Add("BCM", "301290000007");
            banks.Add("BOC", "104100000004");
            banks.Add("CCB", "105100000017");
            banks.Add("CEB", "303100000006");
            banks.Add("CGB", "306331003281");
            banks.Add("CIB", "309391000011");
            banks.Add("CITIC", "302100011000");
            banks.Add("CMB", "308584000013");
            banks.Add("CMBC", "305100000013");
            banks.Add("HXB", "304100040000");
            banks.Add("ICBC", "102100099996");
            banks.Add("PSBC", "403100000004");
            banks.Add("SPDB", "310290000013");
            banks.Add("PAB", "307584007998");
            return banks[bank_code];
        }

        public Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type, PayChannel channel = PayChannel.None)
        {
            throw new NotImplementedException();
        }

        public Task<native_result> NativePay(native_model obj)
        {
            throw new NotImplementedException();
        }

        public async Task<string> Notify(string merchant_no, string order_no)
        {
            string result = string.Empty;
            charge_dto order = _iChargeService.Get(merchant_no, order_no);
            try
            {
                var data = new pay_notity
                {
                    tran_amount = ((int)(order.order_amount * 100)).ToString(),
                    order_no = order.order_no,
                    transaction_no = order.pay_info.transaction_no,
                    pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
                    status = (order.status == ChargeStatus.Finish ? 1 : 2)
                };

                data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
                if (string.IsNullOrEmpty(order.notify)) return "OK";
                var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
                result = notify_result.data;
                var log = IocHelper.Get<ILogHelper>("info");
                log.Info(order.order_no + ":" + notify_result.ToJson());
            }
            catch (Exception ex)
            {
                var log = IocHelper.Get<ILogHelper>("info");
                log.Error("订单通道查询异常:" + order.order_no);
                string message = string.Format("消息类型：{0}\r\n消息内容：{1}\r\n引发异常的方法：{2}\r\n引发异常源：{3}"
                                , ex.GetType().Name, ex.Message, ex.TargetSite, ex.Source + ex.StackTrace);
                log.Error(message);
            }
            return result;
        }

        public Task<string> NotifyTransfer(string merchant_no, string order_no)
        {
            throw new NotImplementedException();
        }

        public async Task<quick_pay_result> QuickPay(quick_pay_model model)
        {
            var binder = _iMerchantService.Get(model.bind_no);
            var setting = _iSettingService.Get();
            string pay_code = model.pay_code;
            model.settle_type = "T0";
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == model.pay_channel);
            var settle = payment.settles.First(c => c.settle_type == model.settle_type && c.code == pay_code);
            if (model.settle_fee / 100M != settle.settle)
                return ApiResultToJson.Json<quick_pay_result>("结算费与商户进件的结算费不同");
            if (model.fee != settle.fee)
                return ApiResultToJson.Json<quick_pay_result>("费率与商户进件的费率不同");
            if (model.pay_fee_amount != (int)Math.Ceiling(decimal.Parse(model.tran_amount) * model.fee))
                return ApiResultToJson.Json<quick_pay_result>("实扣费率金额不正确");
            var merchantRegister = _iMerchantService.GetRegister(model.id_card, model.pay_channel);
            if (merchantRegister != null)
            {
                var id = Guid.NewGuid().ToString("N");
                var notify = setting.site.api_url + "/rpayBh_back_notify/" + id;
                var dt = DateTime.Now.ToString("yyyyMMddHHmmss");
                decimal amt = decimal.Parse(model.tran_amount) / 100M;

                var pay_model = new rpayBh127_pay_req
                {
                    nonce_str = DtoHelper.RandCode(10),
                    pay_type = "12703",
                    mch_id = merchantRegister.merchant_no,
                    terminal_time = dt,
                    total_fee = model.tran_amount,
                    phoneNo = model.mobile,
                    customerName = model.account_name,
                    cerdId = model.id_card,
                    acctNo = model.account_no,
                    exp_date = model.vaild,
                    bankname_withdraw = merchantRegister.bank_name,
                    acctNo_withdraw = merchantRegister.account_no,
                    customerNamewithdraw = merchantRegister.account_name,
                    fee0 = (model.fee * 1000).ToString("0.0"),
                    d0fee = ((int)(settle.settle * 100)).ToString(),
                    money_withdraw = ((int)(((amt - amt * model.fee - settle.settle).RoundDown(2)) * 100)).ToString(),
                    out_order_no = model.order_no,
                    notify_url = notify,
                    return_url = model.front_notify
                };
                var resultApi = await _rpay127Sign.PayGateway<rpayBh127_pay_resp>(pay_model, "/api/jfv1/order");
                if (resultApi != null)
                {
                    if (resultApi.status == "0000")
                    {
                        if (resultApi.result_code == "0000")
                        {
                            var charge = _iChargeService.AddByQuickPay(model);
                            //将HTML保存到mongodb
                            var ok = _iPayHtmlService.Save(new pay_html_dto { id = id, html = resultApi.order_no, merchant_no = model.merchant_no, order_no = model.order_no, charge = charge.ToJson() });
                            if (ok)
                            {
                                return ApiResultToJson.Json("鉴权成功，待确认支付", new quick_pay_result
                                {
                                    order_no = model.order_no,
                                    protocol_no = "",
                                    request_url = resultApi.url,
                                    pay_time = DateTime.Now,
                                    transaction_no = "",
                                    status = 3
                                });
                            }
                            else
                                return ApiResultToJson.Json<quick_pay_result>("支付页面加载失败");
                        }
                        else
                            return ApiResultToJson.Json<quick_pay_result>(resultApi.message);
                    }
                }
            }

            return ApiResultToJson.Json<quick_pay_result>("异常支付");
        }

        public Task<quick_pay_result> QuickPay(quick_sms_model model)
        {
            throw new NotImplementedException();
        }

        public Task<pay_notity> QuickPayQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefund(refund_model model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefundQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model)
        {
            throw new NotImplementedException();
        }

        public Task<quota_result> Quota(string merchant_no, string busiType)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> ReTransfer(long id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransfer(long id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> Transfer(apply_transfer model)
        {
            throw new NotImplementedException();
        }

        public Task<batch_transfer_result> Transfer(batch_transfer model)
        {
            throw new NotImplementedException();
        }

        public Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id)
        {
            throw new NotImplementedException();
        }

        public Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TransferQuery(transfer_query model)
        {
            throw new NotImplementedException();
        }
    }
}
